#include <cmath>
#include <ctime>
#include <algorithm>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>


#include "SimpleMC.h"
MonteCarlo::MonteCarlo(double spot,const Parameter& r,const Parameter& vol)
	:m_spot(spot),m_r(r),m_vol(vol)
{

}

double MonteCarlo::calcPrice(int paths,const SolvableMonteCarlo& option)
{
	double tau = option.getExpiry();
	double variance = m_vol.integralsqaure(0,tau);
	double sd = sqrt(variance);
	double drift = m_spot*exp(m_r.integral(0,tau)-0.5*variance);
	double discount = exp(-1.0*m_r.integral(0,tau));

	boost::mt19937 gen(time(0));
	boost::random::normal_distribution<> normal;

	double sum_payoff = 0.0;
	for(int i=0; i<paths; ++i){
		double diffusion = exp(sd * normal(gen));
		double s_t = drift*diffusion;

		double payoff = option.calcFinalPayOff(s_t);
		sum_payoff += payoff;
	}
	double mean = sum_payoff/paths;
	return mean*discount;
}